﻿/*
使用示例：

1. 在文件开头设置当前文件的日志级别：
   SET_FILE_LOG_LEVEL(Debug);  // 设置当前文件的日志级别为Debug

2. 在代码中使用日志：
   logDebug() << "这是一条调试信息";
   logInfo() << "这是一条信息";
   
   // 如果全局日志级别是Info，但当前文件级别是Debug
   // 则这个文件中的Debug日志会被打印，而其他文件中的Debug日志会被忽略

3. 动态修改特定文件的日志级别：
   Logger::setFileLogLevel("myfile.cpp", Logger::Debug);
   
4. 获取特定文件的日志级别：
   Logger::LogLevel level = Logger::getFileLogLevel("myfile.cpp");
*/

#pragma once

#include <memory>
#include <QObject>
#include <QString>
#include <QTextStream>
#include <unordered_map>
#include <string>

// 前置声明避免包含庞大的spdlog头文件
namespace spdlog {
	class logger;
	namespace level {
		enum level_enum : int;
	}
}

class Logger : public QObject {
	Q_OBJECT

public:
	// 使用不同名称避免与spdlog::level冲突
	enum LogLevel {
		Trace,
		Debug,
		Info,
		Warning,
		Error,
		Critical,
		Off
	};

	static Logger* instance();

	// 日志记录方法
	void log(LogLevel level, const QString& message, const char* file, int line, const char* function);
	void debug(const QString& message, const char* file = nullptr, int line = 0, const char* function = nullptr);
	void info(const QString& message, const char* file = nullptr, int line = 0, const char* function = nullptr);
	void warning(const QString& message, const char* file = nullptr, int line = 0, const char* function = nullptr);
	void error(const QString& message, const char* file = nullptr, int line = 0, const char* function = nullptr);
	void critical(const QString& message, const char* file = nullptr, int line = 0, const char* function = nullptr);

	// 崩溃日志相关方法
	static void writeCrashLog(const QString& crashInfo);
	void setCrashLogPath(const QString& path);
	QString crashLogPath() const;

	// 文件级别日志控制
	static void setFileLogLevel(const char* file, LogLevel level);
	static LogLevel getFileLogLevel(const char* file);
	bool shouldLog(LogLevel msgLevel, const char* file) const;

	static QString extractFileName(const char* fullPath);

	// 配置方法
	void setLevel(LogLevel level);
	LogLevel level() const;
	void setFilePath(const QString& path);
	void setMaxFileSize(size_t maxSize);
	void setMaxFiles(size_t maxFiles);
	void setPattern(const QString& pattern);
	void setAsyncMode(bool enabled);
	void flush();

	// 加载和保存配置
	bool loadConfig(const QString& configFile);
	bool saveConfig(const QString& configFile) const;

private:
	Logger(QObject* parent = nullptr);
	~Logger();

	// 初始化日志器
	void initialize();
	void setupConsoleLogger();
	void setupFileLogger();

	// 转换辅助方法
	spdlog::level::level_enum toSpdLogLevel(LogLevel level) const;
	LogLevel fromSpdLogLevel(spdlog::level::level_enum level) const;

	// 文件级别日志控制
	static std::unordered_map<std::string, LogLevel>& getFileLogLevels();
	static std::unordered_map<std::string, LogLevel> s_fileLogLevels;

	//输出文件格式路径简化
	std::shared_ptr<spdlog::logger> m_consoleLogger;
	std::shared_ptr<spdlog::logger> m_fileLogger;

	QString m_logPath;
	QString m_crashLogPath;  // 添加崩溃日志路径
	QString m_logPattern;
	size_t m_maxFileSize;
	size_t m_maxFiles;
	LogLevel m_level;
	bool m_asyncMode;

	static Logger* s_instance;
};

// 流式日志类
class LogStream {
public:
	LogStream(Logger::LogLevel level, const char* file, int line, const char* function);
	~LogStream();

	template <typename T>
	LogStream& operator<<(const T& value) {
		if (m_shouldLog) {
			m_buffer << value;
		}
		return *this;
	}
     // C风格字符串专用处理 - 添加此重载
    LogStream& operator<<(const char* value) {
        if (m_shouldLog && value) {
            // 将本地编码字符串转换为QString
            m_buffer << QString::fromLocal8Bit(value);
        }
        return *this;
    }
    
    // std::string专用处理 - 添加此重载
    LogStream& operator<<(const std::string& value) {
        if (m_shouldLog) {
            // 从本地编码转换
            m_buffer << QString::fromLocal8Bit(value.c_str(), value.length());
        }
        return *this;
    }
private:
	Logger::LogLevel m_level;
	const char* m_file;
	int m_line;
	const char* m_function;
	bool m_shouldLog;
	QString m_string;
	QTextStream m_buffer;
};

// 文件日志级别设置类（用于替代宏）
class FileLogLevelSetter {
public:
	FileLogLevelSetter(const char* file, Logger::LogLevel level) {
		Logger::setFileLogLevel(file, level);
	}
};

// 修改为宏定义形式，避免在函数声明中使用__FUNCTION__
#define logTrace() LogStream(Logger::Trace, __FILE__, __LINE__, __FUNCTION__)
#define logDebug() LogStream(Logger::Debug, __FILE__, __LINE__, __FUNCTION__)
#define logInfo() LogStream(Logger::Info, __FILE__, __LINE__, __FUNCTION__)
#define logWarning() LogStream(Logger::Warning, __FILE__, __LINE__, __FUNCTION__)
#define logError() LogStream(Logger::Error, __FILE__, __LINE__, __FUNCTION__)
#define logCritical() LogStream(Logger::Critical, __FILE__, __LINE__, __FUNCTION__)

// 基于对象的流式日志函数
#define logObjectDebug() logDebug() << "[" << this->metaObject()->className() << "] "
#define logObjectInfo() logInfo() << "[" << this->metaObject()->className() << "] "
#define logObjectWarning() logWarning() << "[" << this->metaObject()->className() << "] "
#define logObjectError() logError() << "[" << this->metaObject()->className() << "] "
#define logObjectCritical() logCritical() << "[" << this->metaObject()->className() << "] "

// 设置文件日志级别的宏
#define SET_FILE_LOG_LEVEL(level) static FileLogLevelSetter _fileLogLevelSetter(__FILE__, Logger::level);

// 更清晰的日志宏，统一参数数量
#define LOG_TRACE(msg) Logger::instance()->log(Logger::Trace, msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_DEBUG(msg) Logger::instance()->log(Logger::Debug, msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_INFO(msg) Logger::instance()->log(Logger::Info, msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_WARN(msg) Logger::instance()->log(Logger::Warning, msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_ERROR(msg) Logger::instance()->log(Logger::Error, msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_CRITICAL(msg) Logger::instance()->log(Logger::Critical, msg, __FILE__, __LINE__, __FUNCTION__)

// 基于对象的日志宏
#define LOG_OBJECT_DEBUG(msg) Logger::instance()->log(Logger::Debug, QString("[%1] %2").arg(this->metaObject()->className()).arg(msg), __FILE__, __LINE__, __FUNCTION__)
#define LOG_OBJECT_INFO(msg) Logger::instance()->log(Logger::Info, QString("[%1] %2").arg(this->metaObject()->className()).arg(msg), __FILE__, __LINE__, __FUNCTION__)
#define LOG_OBJECT_WARN(msg) Logger::instance()->log(Logger::Warning, QString("[%1] %2").arg(this->metaObject()->className()).arg(msg), __FILE__, __LINE__, __FUNCTION__)
#define LOG_OBJECT_ERROR(msg) Logger::instance()->log(Logger::Error, QString("[%1] %2").arg(this->metaObject()->className()).arg(msg), __FILE__, __LINE__, __FUNCTION__)
#define LOG_OBJECT_CRITICAL(msg) Logger::instance()->log(Logger::Critical, QString("[%1] %2").arg(this->metaObject()->className()).arg(msg), __FILE__, __LINE__, __FUNCTION__)

// 声明Qt消息处理函数，供main.cpp使用
void myMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);